package com.dtp.core.support;

import com.dtp.common.queue.VariableLinkedBlockingQueue;
import com.dtp.core.thread.EagerDtpExecutor;
import org.springframework.lang.NonNull;

import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 在EagerDtpExecutor中的任务队列，主要用于io密集型场景
 *
 * @author yanhom
 * @since 1.0.3
 *
 * @remark muse
 **/
public class TaskQueue extends VariableLinkedBlockingQueue<Runnable> {
    private static final long serialVersionUID = -1L;

    private transient EagerDtpExecutor executor; // Eager类型动态线程池

    public TaskQueue(int queueCapacity) {super(queueCapacity);}

    public void setExecutor(EagerDtpExecutor exec) {executor = exec;}

    /**
     * 向队列中添加任务
     */
    @Override
    public boolean offer(@NonNull Runnable runnable) {
        if (executor == null) throw new RejectedExecutionException("The task queue does not have executor.");

        // 如果当前线程数等于线程池设置的最大线程数，则将任务放入队列中，并结束流程
        int currentPoolThreadSize = executor.getPoolSize();
        if (currentPoolThreadSize == executor.getMaximumPoolSize()) return super.offer(runnable);

        // 如果有空闲的worker（待执行任务数 < 当前线程池中线程数）。把task放入队列中，让worker处理task
        if (executor.getSubmittedTaskCount() < currentPoolThreadSize) return super.offer(runnable);

        // 如果当前线程池中的线程数量小于最大线程池数，则返回false，让executor创建新的worker.
        if (currentPoolThreadSize < executor.getMaximumPoolSize()) return false;

        // 如果currentPoolThreadSize >= max，则直接将任务放入队列中
        return super.offer(runnable);
    }

    /**
     * 强行将任务放入队列
     */
    public boolean force(Runnable o, long timeout, TimeUnit unit) throws InterruptedException {
        if (executor.isShutdown()) throw new RejectedExecutionException("Executor is shutdown.");

        // 在timeout时间内，强行将任务放入队列
        return super.offer(o, timeout, unit);
    }
}
